﻿using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
using System.Windows.Input;
using VisualWip.PresentationModel;

namespace VisualWip
{
    /// <summary>
    /// Interaction logic for Board.xaml
    /// </summary>
    public partial class Board : UserControl
    {
        private BoardViewModel _boardViewMode;
        private Point _lastMousePosition;
        private ZoomableCanvas _myCanvas;

        public Board()
        {
            InitializeComponent();
            DataContextChanged += BoardDataContextChanged;
        }

        private void BoardDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            _boardViewMode = DataContext as BoardViewModel;
        }


        private void AttachSizeAndPositionAdorner(object sender, RoutedEventArgs e)
        {
            var mySender = sender as ContentPresenter;
            if (mySender != null)
            {
                AdornerLayer layer = AdornerLayer.GetAdornerLayer(mySender);
                var viewModel = mySender.Content as ColumnViewModelBase;
                if (layer != null && viewModel != null)
                {
                    var sizeAndPositionAdornerView = new SizeAndPositionAdornerView {DataContext = viewModel};
                    layer.Add(new UiElementAdorner<SizeAndPositionAdornerView>(mySender,
                                                                               sizeAndPositionAdornerView));
                }
            }
        }

        private void ZoomableCanvasLoaded(object sender, RoutedEventArgs e)
        {
            _myCanvas = (ZoomableCanvas) sender;
        }


        protected override void OnPreviewMouseMove(MouseEventArgs e)
        {
            Point position = e.GetPosition(MyBoard);
            if (e.LeftButton == MouseButtonState.Pressed
                && !(e.OriginalSource is Thumb)) // Don't block the scrollbars.
            {
                CaptureMouse();
                SetPanningOrZooming(true);
                Pan(position);
                e.Handled = true;
            }
            else
            {
                ReleaseMouseCapture();
                SetPanningOrZooming(false);
            }
            _lastMousePosition = position;
        }

        private void Pan(Point position)
        {
            _myCanvas.Offset -= position - _lastMousePosition;
        }

        private void SetPanningOrZooming(bool isPanningOrZooming)
        {
            if (_boardViewMode != null)
            {
                foreach (ColumnViewModelBase columnViewModelBase in _boardViewMode.ColumnViewModels)
                {
                    columnViewModelBase.IsPanningOrZooming = isPanningOrZooming;
                }
            }
        }

        protected override void OnPreviewMouseWheel(MouseWheelEventArgs e)
        {
            double scaleFactor = Math.Pow(2, e.Delta/3.0/Mouse.MouseWheelDeltaForOneLine);

            if (_boardViewMode != null)
            {
                double scale = _boardViewMode.Scale*scaleFactor;
                if (_boardViewMode.ZoomManager.CanZoomTo(scale))
                {
                    SetPanningOrZooming(true);
                    _boardViewMode.ZoomManager.ZoomTo(scale);

                    AdjustOffset(e, scaleFactor);

                    e.Handled = true;
                    SetPanningOrZooming(false);
                }
            }
        }

        //Adjust the offset to make the point under the mouse stay still.
        private void AdjustOffset(MouseWheelEventArgs e, double x)
        {
            var position = (Vector) e.GetPosition(MyBoard);
            _myCanvas.Offset = (Point) ((Vector)
                                        (_myCanvas.Offset + position)*x - position);
        }
    }
}